package com.cx.simpleweb.config;

import com.cx.simpleweb.dto.ApiRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

/**
 * @author cxx
 * @create 2021-01-13 15:47
 **/
public class GateWayRequestMatcher implements RequestMatcher {

    private String gateWay = null;

    private Map<String,List<ConfigAttribute>> serviceMap = new HashMap<> ();

    private static final ThreadLocal<String> SERVICE = new ThreadLocal<> ();

    private AntPathMatcher matcher = new AntPathMatcher ();

    private ObjectMapper objectMapper = new ObjectMapper ();

    @Override
    public boolean matches(HttpServletRequest request) {
        String method = request.getMethod ();
//        if(!"POST".equals (method)){
//            return false;
//        }
        String uri = request.getRequestURI ();
        if (matcher.match (gateWay,uri)) {
            try {
                ApiRequest apiRequest = objectMapper.readValue (request.getInputStream (), ApiRequest.class);
                String service = apiRequest.getService ();
                SERVICE.set (service);
                return true;
            } catch (IOException e) {
                return true;
            }
        }
        return false;
    }

    public GateWayRequestMatcher addMatcherUrl(String url){
        if(gateWay == null){
            gateWay = url;
        }else{
            throw new RuntimeException ("only add once 'addMatcherUrl'");
        }
        return this;
    }


    public String getService(){
        return SERVICE.get ();
    }

    public GateWayRequestMatcher addService(String service,String... roles){
        if(roles == null){
            serviceMap.put (service,Collections.emptyList ());
        }else{
            preAddRoleHandler(roles);
            serviceMap.put (service,SecurityConfig.createList (roles));
        }
        return this;
    }

    private void preAddRoleHandler(String[] roles) {
        for (int i = 0; i < roles.length; i++) {
            roles[i] = "ROLE_"+roles[i];
        }
    }

    public List<ConfigAttribute> getCurrentConfigAttribute(){
        return serviceMap.get (SERVICE.get ());
    }

    public Collection<ConfigAttribute> getAllConfigAttributes() {
        LinkedList<ConfigAttribute> list = new LinkedList<> ();
        Set<Map.Entry<String, List<ConfigAttribute>>> set = serviceMap.entrySet ();
        for (Map.Entry<String, List<ConfigAttribute>> entry : set) {
            list.addAll (entry.getValue ());
        }
        return list;
    }
}
